use super::row::Row;
use crate::core::group::Group;
use anyhow::Result;

const CRLF: &str = "\r\n";

struct Content {}

impl Content {
    pub fn parse(content: &'static str) -> Result<Group> {
        let mut group = Group::new("root");
        let mut line_num: usize = 1;
        let lines: Vec<&str> = content.split(CRLF).collect();
        for line in lines {
            let row_result = Row::parse(line);
            match row_result {
                Ok(row) => {
                    Self::add(&mut group, row);
                }
                Err(_) => {
                    return Err(anyhow!("parse err on line: {}", line_num));
                }
            };
            line_num += 1;
        }
        return Ok(group);
    }

    fn add(group: &mut Group, row: Row) {
        match row {
            Row::G((level, group_data)) => {
                group.add_node_by_level(level, group_data);
            }
            Row::I((level, item)) => {
                group.add_item_by_level(level, item);
            }
        }
    }
}

mod tests {
    use super::*;

    #[test]
    fn parse_work() {
        let content_vec = vec![
            "i[\"测试标题\", \"jduare\", \"password1\"]",
            "i[\"测试标题\", \"jduare\", \"password1\"]",
        ];
        let content_string = content_vec.join(CRLF);
        let content = string_to_static_str(content_string);
        let group = Content::parse(content).unwrap();
        assert_eq!(group.root().data().items().len(), 2);

        let content_vec = vec!["g[group1]"];
        let content_string = content_vec.join(CRLF);
        let content = string_to_static_str(content_string);
        let group = Content::parse(content).unwrap();
        assert_eq!(group.root().children().len(), 1);
        assert!(group.root().last_child().is_some());
        assert_eq!(group.root().last_child().unwrap().data().name(), "group1");

        let content_vec = vec![
            "g[group1]",
            "  i[\"测试标题\", \"jduare\", \"password1\"]",
            "  i[\"测试标题\", \"jduare\", \"password1\"]",
            "g[group2]",
            "  g[group3]",
            "    i[\"测试标题\", \"jduare\", \"password1\"]",
            "    i[\"测试标题\", \"jduare\", \"password1\"]",
        ];
        let content_string = content_vec.join(CRLF);
        let content = string_to_static_str(content_string);
        let group = Content::parse(content).unwrap();
        assert_eq!(group.root().children().len(), 2);
        assert!(group.root().last_child().is_some());
        assert_eq!(group.root().last_child().unwrap().data().name(), "group2");
        assert_eq!(group.root().last_child().unwrap().data().items().len(), 0);
        assert_eq!(group.root().last_child().unwrap().children().len(), 1);
        assert_eq!(
            group
                .root()
                .last_child()
                .unwrap()
                .last_child()
                .unwrap()
                .data()
                .name(),
            "group3"
        );
        assert_eq!(
            group
                .root()
                .last_child()
                .unwrap()
                .last_child()
                .unwrap()
                .data()
                .items()
                .len(),
            2
        );
    }

    fn string_to_static_str(s: String) -> &'static str {
        Box::leak(s.into_boxed_str())
    }
}
